﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Text.RegularExpressions;
using Dapper;
namespace NFinalCompiler.Sql
{
    public class SqlDocument
    {
        public Dictionary<string, string> varList = new Dictionary<string, string>();
        public bool generateAllTable = true;
        public string[] generateTables = null;
        public bool generateAllEnum = true;
        public string[] generateEnumCategories = null;
        public string generateMode = "model";
        public string name = null;
        public string modelNameSpace = null;
        public string bllNameSpace = null;
        public string enumNameSpace = null;
        public string connectionString = null;
        public string selectEnumDataSql = null;
        public string providerName = null;

        public Dictionary<string, string> sqlList = new Dictionary<string, string>();
        public List<ModelFileData> modelFileDataList = new List<ModelFileData>();
        public List<string> fileNameList = new List<string>();
        public static string nameSpace;
        public SqlDocument(string filePath, string nameSpace, string sqlContent)
        {
            SqlDocument.nameSpace = nameSpace;
            modelNameSpace = nameSpace;
            bllNameSpace = nameSpace;
            string fileDirectory = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(fileDirectory))
            {
                Directory.CreateDirectory(fileDirectory);
            }
            string fileName=string.Empty;
            NFinal.IO.StringWriter sw = null;
            ModelFileData modelData;
            System.Data.Common.DbConnection con = null;
            #region 读取配置
            Regex varRegex = new Regex(@"set\s+@([_a-zA-Z0-9]+)=('.*'|.*)(\r|\n)*", RegexOptions.IgnoreCase);
            MatchCollection varMac = varRegex.Matches(sqlContent);
            string key = null;
            string value = null;
            foreach (Match varMat in varMac)
            {
                if (varMat.Success)
                {
                    key = varMat.Groups[1].Value;
                    value = varMat.Groups[2].Value.Trim().Trim('\'');
                    if (!string.IsNullOrEmpty(key))
                    {
                        if (key == "generateTables")
                        {
                            if (value == "*" || value == "")
                            {
                                generateAllTable = true;
                                generateTables = null;
                            }
                            else
                            {
                                generateAllTable = false;
                                generateTables = value.Split(',', ';');
                            }
                        }
                        if (key == "generateEnumCategories")
                        {
                            if (value == "*" || value == "")
                            {
                                generateAllEnum = true;
                                generateEnumCategories = null;
                            }
                            else
                            {
                                generateAllEnum = false;
                                generateEnumCategories = value.Split(',',';');
                            }
                        }
                        else if (key == "name")
                        {
                            this.name = value;
                        }
                        else if (key == "modelNameSpace")
                        {
                            if (!string.IsNullOrEmpty(value))
                            {
                                this.modelNameSpace = value.Trim('.');
                            }
                        }
                        else if (key == "bllNameSpace")
                        {
                            if (!string.IsNullOrEmpty(value))
                            {
                                this.bllNameSpace = value.Trim('.');
                            }
                        }
                        else if (key == "enumNameSpace")
                        {
                            if (!string.IsNullOrEmpty(value))
                            {
                                this.enumNameSpace = value.Trim('.');
                            }
                        }
                        else if (key == "generateMode")
                        {
                            if (!string.IsNullOrEmpty(value))
                            {
                                generateMode = value;
                            }
                            else
                            {
                                generateMode = "model";
                            }
                        }
                        else if (key == "connectionString")
                        {
                            this.connectionString = value;
                        }
                        else if (key == "providerName")
                        {
                            this.providerName = value;
                        }
                        else if (key == "selectEnumDataSql")
                        {
                            this.selectEnumDataSql = value.Replace("\'\'", "\'");
                        }
                    }
                }
            }
            #endregion
            Data.DataUtility dataUtility = null;
            string id= AppDomain.CurrentDomain.BaseDirectory;
            string dataBaseType = "";
            try
            {
                if (!string.IsNullOrEmpty(this.name) && !string.IsNullOrEmpty(this.connectionString) && !string.IsNullOrEmpty(this.providerName))
                {
                    if (this.providerName.ToLower().IndexOf("mysql") > -1)
                    {
                        dataBaseType = "mysql";
                        con = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
                        dataUtility = new Data.MySqlDataUtility(con);
                    }
                    else if (this.providerName.ToLower().IndexOf("sqlite") > -1)
                    {
                        dataBaseType = "sqlite";
                        con = new System.Data.SQLite.SQLiteConnection(connectionString);
                        dataUtility = new Data.SQLiteDataUtility(con);
                    }
                    else if (this.providerName.ToLower().IndexOf("sqlclient") > -1)
                    {
                        dataBaseType = "sqlserver";
                        con = new System.Data.SqlClient.SqlConnection(connectionString);
                        dataUtility = new Data.SqlServerDataUtility(con);
                    }
                    else if (this.providerName.ToLower().IndexOf("Oracle") > -1)
                    {
                        dataBaseType = "oracle";
                        con = new Oracle.ManagedDataAccess.Client.OracleConnection(connectionString);
                        dataUtility = new Data.OracleDataUtility(con);
                    }
                    else if (this.providerName.ToLower().IndexOf("Npgsql") > -1)
                    {
                        dataBaseType = "npgsql";
                        con = new Npgsql.NpgsqlConnection(connectionString);
                        dataUtility = new Data.PostgreSqlDataUtility(con);
                    }

                    dataUtility.Open();
                    #region 老的生成
                    //if (false)
                    //{
                    //    var tableDataList = dataUtility.GetDefaultTableData();
                    //    if (dataUtility != null)
                    //    {
                    //        //dataUtility.SetTableColumnData(tableDataList);
                    //        foreach (var tableData in tableDataList)
                    //        {
                    //            fileName = Path.Combine(fileDirectory, tableData.Name + ".cs");
                    //            if (!File.Exists(fileName))
                    //            {
                    //                modelData = new ModelFileData();
                    //                modelData.tableAttribute = this.tableAttribute;
                    //                modelData.columnAttribute = this.columnAttribute;
                    //                modelData.keyAttribute = this.keyAttribute;
                    //                modelData.name = tableData.Name;
                    //                modelData.nameSpace = nameSpace;
                    //                modelData.isDefaultTable = true;
                    //                dataUtility.SetTableColumnData(tableData);
                    //                sw = new NFinal.IO.StringWriter();
                    //                ModelTemplateRazor template = new ModelTemplateRazor(sw, tableData);
                    //                template.Execute();
                    //                modelData.content = sw.ToString();
                    //                modelData.fileName = fileName;
                    //                modelFileDataList.Add(modelData);
                    //            }
                    //        }
                    //    }
                    //}
                    #endregion
                    if (generateMode == "enum")
                    {
                        if (string.IsNullOrWhiteSpace(selectEnumDataSql))
                        {
                            Helper.Logger.Log("连接字符串不能为空");
                            return;
                        }
                        var systemEnumInfos = con.Query<SqlModel.SystemEnumInfo>(selectEnumDataSql);
                        SqlModel.EnumModelData enumModelData = null;
                        string categoryDir = null;
                        foreach (var systemEnumInfo in systemEnumInfos)
                        {
                            fileName = Path.Combine(fileDirectory, systemEnumInfo.EnumName + ".cs");
                            if (!File.Exists(fileName))
                            {
                                enumModelData = new SqlModel.EnumModelData()
                                {
                                    NameSpace = enumNameSpace,
                                    SystemEnumInfo = systemEnumInfo,
                                };
                                sw = new NFinal.IO.StringWriter();
                                SqlModel.NetStandard.EnumNewRazor enumRazor = new SqlModel.NetStandard.EnumNewRazor(sw, enumModelData);
                                enumRazor.Execute();

                                modelData = new ModelFileData();
                                modelData.fileName = fileName;
                                modelData.content = sw.ToString();
                                modelFileDataList.Add(modelData);
                            }
                        }
                    }
                    else
                    {
                        if (generateMode != "model" && generateMode != "bll")
                        {
                            return;
                        }
                        #region 新的生成
                        IList<DatabaseSchemaReader.DataSchema.DatabaseTable> generateTalbeList = null;
                        var dbReader = new DatabaseSchemaReader.DatabaseReader(con);
                        dbReader.Owner = con.Database;
                        if (generateAllTable)
                        {
                            dbReader.DataTypes();
                            var tableList= dbReader.TableList();
                            generateTalbeList = new List<DatabaseSchemaReader.DataSchema.DatabaseTable>();
                            for(int i=0;i<tableList.Count;i++)
                            {
                                if (generateMode == "model")
                                {
                                    fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(tableList[i].Name) + "Info.cs");
                                }
                                if (generateMode == "bll")
                                {
                                    fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(tableList[i].Name) + "BLL.cs");
                                }
                                if (!File.Exists(fileName))
                                {
                                    generateTalbeList.Add(dbReader.Table(tableList[i].Name));
                                }
                            }
                        }
                        else
                        {
                            dbReader.DataTypes();
                            generateTalbeList = new List<DatabaseSchemaReader.DataSchema.DatabaseTable>();
                            foreach (var generateTable in generateTables)
                            {
                                //dbReader.DataTypes();
                                if (generateMode == "model")
                                {
                                    fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(generateTable) + "Info.cs");
                                }
                                if (generateMode == "bll")
                                {
                                    fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(generateTable) + "BLL.cs");
                                }
                                if (!File.Exists(fileName))
                                {
                                    generateTalbeList.Add(dbReader.Table(generateTable));
                                }
                            }
                        }

                        //Then load the schema (this will take a little time on moderate to large database structures)
                        //Dictionary<string, SqlModel.SystemEnumInfo> systemEnumInfoDic = null;
                        //if (generateMode == "model")
                        //{
                        //    using (MySql.Data.MySqlClient.MySqlConnection enumConnection = new MySql.Data.MySqlClient.MySqlConnection(enumConnectionString))
                        //    {
                        //        var systemEnumInfos = enumConnection.Query<SqlModel.SystemEnumInfo>("select * from c_system_enum").ToList();
                        //        systemEnumInfoDic = systemEnumInfos.ToDictionary(x => x.Name);
                        //    }
                        //}
                        foreach (var table in generateTalbeList)
                        {
                            SqlModel.ModelData modelDataSchema = new SqlModel.ModelData();
                            modelDataSchema.BLLNameSpace = bllNameSpace;
                            modelDataSchema.ModelNameSpace = modelNameSpace;
                            modelDataSchema.DataBaseName = con.Database;
                            modelDataSchema.DataBaseShortName = this.name;
                            modelDataSchema.DataBaseType = dataBaseType;
                            modelDataSchema.Table = table;
                            if (generateMode == "model")
                            {
                                modelDataSchema.EnumNameSpace = enumNameSpace;
                                //modelDataSchema.systemEnumInfoDic = systemEnumInfoDic;
                                fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(table) + "Info.cs");
                                sw = new NFinal.IO.StringWriter();
                                SqlModel.NetStandard.ModelRazor model_Cshtml = new SqlModel.NetStandard.ModelRazor(sw, modelDataSchema);
                                model_Cshtml.Execute();
                                modelData = new ModelFileData();
                                modelData.fileName = fileName;
                                modelData.content = sw.ToString();
                                modelFileDataList.Add(modelData);
                            }
                            if (generateMode == "bll")
                            {
                                fileName = Path.Combine(fileDirectory, SqlModel.ModelHelper.GetTableName(table) + "BLL.cs");
                                sw = new NFinal.IO.StringWriter();
                                SqlModel.NetStandard.Bll_CacheRepostoryRazor bll_CacheRepostory_Cshtml =
                                    new SqlModel.NetStandard.Bll_CacheRepostoryRazor(sw, modelDataSchema);
                                bll_CacheRepostory_Cshtml.Execute();
                                modelData = new ModelFileData();
                                modelData.fileName = fileName;
                                modelData.content = sw.ToString();
                                modelFileDataList.Add(modelData);
                            }
                        }
                    }
                    #endregion
                }
            }
            catch (Exception ex)
            {
                Helper.Logger.Log(ex);
            }
            finally
            {
                if (dataUtility != null)
                {
                    dataUtility.Close();
                }
            }
            #region
            if (false)
            {
                //sqlContent = sqlContent.Substring(commentMatch.Length);
                //StringReader reader = new StringReader(sqlContent);
                //bool isEnd = false;
                //string line = null;
                //string name = null;
                //string sql = null;
                //while (!isEnd)
                //{
                //    line = reader.ReadLine();
                //    if (line == null)
                //    {
                //        if (!string.IsNullOrEmpty(name))
                //        {
                //            sqlList.Add(name, sql);
                //        }
                //        break;
                //    }
                //    if (line.StartsWith("--"))
                //    {
                //        if (!string.IsNullOrEmpty(name))
                //        {
                //            sqlList.Add(name, sql);
                //        }
                //        name = line.Substring(2).Trim();
                //        sql = null;
                //    }
                //    else
                //    {
                //        sql += line;
                //    }
                //}

                //foreach (var sqlData in sqlList)
                //{
                //    fileName = Path.Combine(fileDirectory, sqlData.Key + ".cs");
                //    if (!File.Exists(fileName))
                //    {
                //        modelData = new ModelFileData();
                //        modelData.fileName = fileName;
                //        modelData.name = sqlData.Key;
                //        modelData.sql = sqlData.Value;
                //        modelData.nameSpace = nameSpace;
                //        modelData.isDefaultTable = false;
                //        Data.TableData tableData = new Data.TableData(modelData.name, modelData.sql);
                //        dataUtility.SetTableColumnData(tableData);
                //        sw = new NFinal.IO.StringWriter();
                //        ModelTemplateRazor modelTemplate = new ModelTemplateRazor(sw, tableData);
                //        modelTemplate.Execute();
                //        modelData.content = sw.ToString();
                //        modelFileDataList.Add(modelData);
                //    }
                //}
            }
            #endregion

        }
    }
}
